package com.gitee.deament.server.core.cli.db.hash;

import cn.hutool.core.util.NumberUtil;
import com.gitee.deament.server.config.SystemConfig;
import com.gitee.deament.server.core.annotation.CliHander;
import com.gitee.deament.server.core.cli.AbstractCli;
import com.gitee.deament.server.core.data.ConnectData;
import com.gitee.deament.server.core.data.datatype.Value;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * HINCRBYFLOAT
 * HINCRBYFLOAT key field increment
 *
 * 为哈希表 key 中的域 field 加上浮点数增量 increment 。
 *
 * 如果哈希表中没有域 field ，那么 HINCRBYFLOAT 会先将域 field 的值设为 0 ，然后再执行加法操作。
 *
 * 如果键 key 不存在，那么 HINCRBYFLOAT 会先创建一个哈希表，再创建域 field ，最后再执行加法操作。
 *
 * 当以下任意一个条件发生时，返回一个错误：
 *
 * 域 field 的值不是字符串类型(因为 redis 中的数字和浮点数都以字符串的形式保存，所以它们都属于字符串类型）
 *
 * 域 field 当前的值或给定的增量 increment 不能解释(parse)为双精度浮点数(double precision floating point number)
 */
@CliHander(command ="HINCRBYFLOAT")
public class HINCRBYFLOATcli extends AbstractCli {
    @Override
    public void executeCli(ChannelHandlerContext channelHandlerContext, String command) {
        List<String> values = getValues(command);
        if (values.size() != 4) {
            channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame("ERR wrong number of arguments for 'HINCRBYFLOAT' command"));
            return;
        }
        int db = ConnectData.SELECT_DB_STORAGE.getUseDB(channelHandlerContext.channel().id().asLongText());
        String hash=values.get(1);
        String field=values.get(2);
        String increaseNum=values.get(3);
        if(!NumberUtil.isNumber(increaseNum)){
            channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame("ERR value is not an integer or out of range"));
        }
        BigDecimal increaseNumber= new BigDecimal(increaseNum) ;
        Value<Map<String, String>> hashData = SystemConfig.dbData.getHashData(db, hash);

        Value<Map<String, String>> newValue= new Value<>();
        Map<String, String> fieldAndValue= new HashMap<>(1);
        fieldAndValue.put(field, increaseNum);
        newValue.setValue(fieldAndValue);
        if(hashData==null||hashData.getValue().get(field)==null){
            SystemConfig.dbData.setHashData(db, hash, field, increaseNum);

            channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame(increaseNum));
        } else{
            Date date = hashData.getExpirDateTime();
            if ((date.compareTo(new Date())) <= 0) {
                SystemConfig.dbData.setHashData(db, hash, field, increaseNum);
                channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame(increaseNum));
                return;
            }
            if(NumberUtil.isInteger(hashData.getValue().get(field))){
                //TODO 线程安全的问题待解决
                fieldAndValue.put(field, increaseNum);
               String value=increaseNumber.add(new BigDecimal(hashData.getValue().get(field))).toString();
                fieldAndValue.put(field, value);
                newValue.setValue(fieldAndValue );
                channelHandlerContext.channel().writeAndFlush(value);
            }else{
                channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame("ERR value is not an integer or out of range"));
                return;

            }
        }
    }
}
